package cn.metona.mq.utils;

import cn.metona.mq.core.Message;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.Map;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

/**
 * 消息工具类
 * 提供消息处理相关的工具方法
 */
public class MessageUtils {
    
    /**
     * 压缩消息体
     */
    public static byte[] compressMessageBody(String body) {
        if (body == null || body.isEmpty()) {
            return new byte[0];
        }
        
        try {
            byte[] input = body.getBytes(StandardCharsets.UTF_8);
            Deflater deflater = new Deflater();
            deflater.setInput(input);
            deflater.finish();
            
            byte[] output = new byte[input.length];
            int compressedLength = deflater.deflate(output);
            deflater.end();
            
            byte[] result = new byte[compressedLength];
            System.arraycopy(output, 0, result, 0, compressedLength);
            return result;
        } catch (Exception e) {
            throw new RuntimeException("Failed to compress message body", e);
        }
    }
    
    /**
     * 解压消息体
     */
    public static String decompressMessageBody(byte[] compressedData) {
        if (compressedData == null || compressedData.length == 0) {
            return "";
        }
        
        try {
            Inflater inflater = new Inflater();
            inflater.setInput(compressedData);
            
            byte[] output = new byte[compressedData.length * 2];
            int decompressedLength = inflater.inflate(output);
            inflater.end();
            
            return new String(output, 0, decompressedLength, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("Failed to decompress message body", e);
        }
    }
    
    /**
     * Base64编码消息体
     */
    public static String encodeMessageBody(String body) {
        if (body == null) {
            return null;
        }
        return Base64.getEncoder().encodeToString(body.getBytes());
    }
    
    /**
     * Base64解码消息体
     */
    public static String decodeMessageBody(String encodedBody) {
        if (encodedBody == null) {
            return null;
        }
        return new String(Base64.getDecoder().decode(encodedBody));
    }
    
    /**
     * 验证消息有效性
     */
    public static boolean isValidMessage(Message message) {
        if (message == null) {
            return false;
        }
        
        // 检查必要字段
        if (message.topic() == null || message.topic().isEmpty()) {
            return false;
        }
        
        if (message.body() == null) {
            return false;
        }
        
        // 检查时间有效性
        if (message.createTime() == null) {
            return false;
        }
        
        // 检查过期时间
        return message.expireTime() == null || !message.expireTime().isBefore(LocalDateTime.now());
    }
    
    /**
     * 计算消息大小（字节）
     */
    public static long calculateMessageSize(Message message) {
        if (message == null) {
            return 0;
        }
        
        long size = 0;
        size += message.messageId() != null ? message.messageId().length() : 0;
        size += message.topic() != null ? message.topic().length() : 0;
        size += message.body() != null ? message.body().length() : 0;
        size += message.tag() != null ? message.tag().length() : 0;
        
        // 计算头部大小
        if (message.headers() != null) {
            for (Map.Entry<String, String> entry : message.headers().entrySet()) {
                size += entry.getKey().length() + entry.getValue().length();
            }
        }
        
        return size;
    }
    
    /**
     * 克隆消息
     */
    public static Message cloneMessage(Message original) {
        if (original == null) {
            return null;
        }
        
        return new Message(
            original.messageId(),
            original.topic(),
            original.body(),
            original.priority(),
            original.createTime(),
            original.expireTime(),
            original.headers() != null ? new java.util.HashMap<>(original.headers()) : null,
            original.tag(),
            original.delayTime()
        );
    }
}